#include "stdafx.h"
#include "StringFunction.h"
#include <algorithm>

#ifdef _WIN32

namespace BaseFunction
{
	std::string Replace(std::string& str, const char* str_to_replace, const char* new_str)
	{
		size_t len = strlen(str_to_replace);
		size_t index = str.find(str_to_replace);
		while (index != std::string::npos)
		{
			str.replace(index, len, new_str);
			index = str.find(str_to_replace, index + strlen(new_str));
		}
		return str;
	}

	std::string Trim(const std::string& str)
	{
		return TrimEnd(TrimStart(str));
	}

	std::string TrimStart(const std::string& str)
	{
		std::string result = str;
		result.erase(0, result.find_first_not_of("\t \r\n"));
		return result;
	}

	std::string TrimEnd(const std::string& str)
	{
		std::string result = str;
		result.erase(result.find_last_not_of("\t \r\n") + 1);
		return result;
	}

	std::wstring StringToWString(const std::string& str)
	{
		int count = ::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, str.c_str(), -1, NULL, 0);
		wchar_t* tmp = new wchar_t[count];
		memset(tmp, 0, count * sizeof(wchar_t));
		::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, str.c_str(), -1, tmp, count);
		std::wstring strres(tmp);
		delete[] tmp;
		tmp = NULL;
		return strres;
	}

	std::string WStringToString(const std::wstring& str)
	{
		int count = ::WideCharToMultiByte(CP_ACP, 0, str.c_str(), -1, NULL, 0, NULL, NULL);
		char* tmp = new char[count];
		memset(tmp, 0, count);
		::WideCharToMultiByte(CP_ACP, 0, str.c_str(), -1, tmp, count, NULL, NULL);
		std::string strres(tmp);
		delete[] tmp;
		tmp = NULL;
		return strres;
	}

	std::string UnicodeToUTF8(const std::wstring& str)
	{
		std::string res;
		for(std::wstring::const_iterator iter = str.begin(); iter != str.end(); ++iter)
		{
			if( *iter < 0x80 )
			{
				res.append(1, (char)*iter);
			}
			else if( *iter < 0x800 )
			{
				res.append(1, ((char)(*iter >> 8)) & 0x1F | 0xC0);
				res.append(1, ((char)(*iter & 0x003F)) | 0x80);
			}
			else if( *iter < 0x10000 )
			{
				res.append(1, (char)((*iter >> 12) & 0x000F) | 0xE0);
				res.append(1, (char)((*iter >> 6) & 0x003F) | 0x80);
				res.append(1, (char)(*iter & 0x003F) | 0x80);
			}
		}
		return res;
	}

	std::wstring UTF8ToUnicode(const std::string& str)
	{
		std::wstring res;
		bool toomuchbyte = true;
		for(std::string::const_iterator iter = str.begin(); iter != str.end(); ++iter)
		{
			if((unsigned char)*iter < 0x80)
			{
				toomuchbyte = false;
				res.append(1, (wchar_t)*iter);
			}
			else if((unsigned char)*iter < 0xC0)
			{		
				//suffix byte
				if( toomuchbyte )
					continue;

				wchar_t wchr = res[res.length() - 1];
				res[res.length() - 1] = (wchr << 6) | (*iter & 0x3F);
			}
			else if((unsigned char)*iter < 0xE0)
			{
				//2 length
				if(iter + 1 == str.end())	//length left MUST NOT less than 2
					break;

				toomuchbyte = false;
				res.append(1, (wchar_t)(*iter & 0x1F));
			}
			else if((unsigned char)*iter < 0xF0)
			{
				//3 length
				if(iter + 2 >= str.end())	//see above
					break;

				toomuchbyte = false;
				res.append(1, (wchar_t)(*iter & 0xF));
			}
			else	//more than two bytes per a Unicode
			{
				//just skip them
				toomuchbyte = true;
			}
		}
		return res;
	}

	std::string GB2312ToUTF8(const std::string& str)
	{
		std::wstring tmp = StringToWString(str);
		return UnicodeToUTF8(tmp);
	}

	std::string UTF8ToGB2312(const std::string& str)
	{
		std::wstring tmp = UTF8ToUnicode(str);
		return WStringToString(tmp);
	}

	std::string TransformToUpper(const std::string& str)
	{
		std::string upstr(str);
		std::transform(upstr.begin(), upstr.end(), upstr.begin(), toupper);
		return upstr;
	}

	std::string TransformToLower(const std::string& str)
	{
		std::string lowstr(str);
		std::transform(lowstr.begin(), lowstr.end(), lowstr.begin(), tolower);
		return lowstr;
	}
}
#endif